﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.Uml.Activities;
using Microsoft.VisualStudio.Uml.Classes;
using Microsoft.VisualStudio.ArchitectureTools.Extensibility.Uml;
using HumanWorkflow.SemanticModel;

namespace HumanWorkflow.Framework
{
    public partial class HumanWorkflowTemplate : HumanWorkflowTemplateBase
    {
        public string ProjectPath {get; set;}
        public string NamespaceName { get; set; }
        public string ClassName { get; set; }
        IModelStore store;

        private bool IsStereotypeApplied(string stereotype, IActivityNode activityNode)
        {
            return activityNode.AppliedStereotypes.Where<IStereotypeInstance>(s => s.Name == stereotype).Count() > 0;
        }

        private string GetStereotypeProperty(string propertyName, IActivityNode activityNode)
        {
            foreach (IStereotypeInstance stereoType in activityNode.AppliedStereotypes)
            {
                foreach (IStereotypePropertyInstance property in stereoType.PropertyInstances)
                {
                    if (property.Name == propertyName)
                    {
                        return property.Value.ToString();
                    }
                }
            }

            throw new Exception("Cann not find property: " + propertyName + " in activity" + activityNode.Name);
        }

        private string GetSemanticStepTypeForActivityNode(IActivityNode activityNode)
        {
            string stepType;

            if (activityNode is IInitialNode)
            {
                stepType = "InitialStep";
            }
            else if (activityNode is IFinalNode)
            {
                stepType = "FinalStep";
            }
            else if (activityNode is IDecisionNode)
            {
                stepType = "DecisionStep";
            }
            else if (IsStereotypeApplied("ManualStep", activityNode))
            {
                stepType = "ManualStep";
            }
            else if (IsStereotypeApplied("AutomaticStep", activityNode))
            {
                stepType = "AutomaticStep";
            }
            else
            {
                stepType = "UnsupprtedActivity";
                this.Error("Unsupported activity type or stereotype.");
            }

            return stepType;
        }

        private string ToPascalCase(string phrase)
        {
            string[] splittedPhrase = phrase.Split(' ', '-', '.');
            var sb = new StringBuilder();

            foreach (String s in splittedPhrase)
            {
                char[] splittedPhraseChars = s.ToCharArray();
                if (splittedPhraseChars.Length > 0)
                {
                    splittedPhraseChars[0] = ((new String(splittedPhraseChars[0], 1)).ToUpper().ToCharArray())[0];
                }
                sb.Append(new String(splittedPhraseChars));
            }
            return sb.ToString();
        }

        List<string> GetDistinctRoles()
        {
            List<string> roleDistinctList = new List<string>();
            string roleName;

            foreach (IActivityNode umlActivityNode in store.AllInstances<IActivityNode>())
            {
                if (GetSemanticStepTypeForActivityNode(umlActivityNode) == "ManualStep")
                {
                    roleName = ToPascalCase(GetStereotypeProperty("Role", umlActivityNode));
                    
                    if (!roleDistinctList.Contains(roleName))
                    {
                        roleDistinctList.Add(roleName);
                    }
                }
            
            }
            
            return roleDistinctList;        
        }
    }
}
